home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Utilities / Programming / EnterAct 3.5 / hAWK project / AWK Source / hAWK_Interface.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-06-15  |  50.6 KB  |  1,954 lines  |  [TEXT/KEEN]

  1. /* hAWK_Interface.c : hAWK dialog interface */
  2. /* Copyright © 1986, 1988, 1989 1991 the Free Software Foundation, Inc.
  3.  *         This file is part of GAWK, the GNU implementation of the
  4.  * AWK Progamming Language, modified for the Macintosh (also called hAWK).
  5.  *         GAWK is free software; you can redistribute or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation; either version 1, or any later version.
  8.  *         GAWK is distributed in the hope that it will be useful,
  9.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11.  * GNU General Public License for more details.
  12.  *         You should have received a copy of the GNU General Public License
  13.  * along with GAWK; see the file "COPYING hAWK". If not, write to
  14.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  15.  * Written for THINK C 4 on the Macintosh by Ken Earle (Dynabyte) Aug 1991.
  16.  */
  17.  
  18. /* Code to synthesize a command line based on user's choices in the
  19. main hAWK dialog. Mouse-driven, except for variables that one wishes
  20. to be set on the command line - these must be typed in.
  21.  
  22. Program options: choose from a list of all hAWK programs in the
  23. folder "hAWK programs", or some other programs via a standard SFGetFile dialog.
  24. "Library" files may also be added - the parser treats them as being appended
  25. to the main program, but for the sake of sanity they should contain only
  26. function definitions.
  27.  
  28. Variables options: not very fancy, just type in "var=value" (not including the quotes)
  29. in the dialog for variables.
  30.  
  31. Input options: here's where the Mac really shines - hAWK has generalized options for
  32. input which allow a program to be run on different input without altering the
  33. dialog setup - that's why its possible and useful to save the setup associated
  34. with a particular hAWK program
  35. - Specific input file; the one "fixed" option, allows user to pick one particular
  36.     input file as input
  37. - Selected front text / All of front text; takes as input all or the selected part
  38.     of the text window that happens to be in front when hAWK is called
  39. - MFS selected files; takes as input all files selected for multi-file operation
  40.     in the calling application - usually multi-file searching.
  41.  
  42. Save settings: saves the dialog options with the hAWK program. Especially useful
  43. for restoring the input option.
  44.  
  45. An "About" button displays copysquawk about hAWK/gawk/awk/nawk.
  46.  
  47. Rev Dec 5/92: Run button always drawn bold in a more-general way,
  48. Set Variables button emboldened if variables are already present for a program.
  49.  
  50. */
  51.  
  52. #include <stdlib.h>
  53. #include <stdio.h>
  54. //#include <fcntl.h>
  55. #include <string.h>
  56. #include <setjmp.h>
  57. #include "CodeResHelper.h" /* TMalloc etc */
  58. #include "CodeResource.h"
  59. #include "AppCodeComm.h"
  60.  
  61. extern void *alloca(unsigned short size);
  62. extern void DumpZoneList(void);
  63. extern void DisposeProgress(void); /* hAWK_prompt.c */
  64.  
  65. /* buffer holding position of long jump */
  66. jmp_buf        envBuf;
  67.  
  68. static short argc;
  69. static char **argv;
  70. static short NUMARGVS = 500; /* Was a #define, now variable */
  71.  
  72. short gInputError; /* Not used yet */
  73.  
  74. /* interface constants and struct recording user choices */
  75. #define NUMLIBS        10        /* max number of libraries */
  76. #define NUMVARSETS        10    /* max number of "command line" variables */
  77. typedef struct HawkSetup
  78.     {
  79.     short        inputType;        /* input file or "metafile" specification */
  80.     Boolean    showOut, selectOut; /* passed back to calling application */
  81.     char     *progname;            /* the hAWK program */
  82.     char     *libraryname[NUMLIBS];
  83.     char    *varsetting[NUMVARSETS];
  84.     char    *inputname; /* optional, if one specific file selected   */
  85.     short        progVRefNum; /* not saved to disk - for currently selected program*/
  86.     short        defaultVRefNum; /* not saved, for the folder "hAWK programs" */
  87.     short        otherVRefNum; /* for "unlisted" program */
  88.     } HawkSetup;
  89. /* global record of user choices */
  90. HawkSetup HS;
  91.  
  92. /* Current popup items. Note the current selection for the input popup is
  93. recorded in HS,inputType. */
  94. static short     mainProgMenuNum = 1,
  95.             libraryMenuNum = 1;
  96.  
  97. /* User choices can be saved with hAWK program for next run */
  98. #define        HAWKID            1011    /* resource id, type 'HAWK' */
  99.  
  100. /* Dialog to set up a hAWK run.
  101. */
  102. #define    HawkDlogID        405
  103. /* OK is 1, Cancel is 2 */
  104. #define SaveHawkSetup    3
  105. #define ProgramStat        5
  106. #define LibraryStat        6
  107. #define InputStat        7
  108. #define VariableButton    8
  109. #define ShowOut            9
  110. #define SelectOut        10
  111. #define ProgramPopup    11
  112. #define LibraryPopup    12
  113. #define InputPopup        13
  114. #define AboutHawk        14
  115. #define RunUserItem        15
  116. #define VarUserItem        16
  117.  
  118. /* popups */
  119. #define MainProgramID    187
  120. #define LibraryID        188
  121. #define InputID            189
  122.  
  123. /* The "Take input from:" popup varies accoring to which extensions
  124. are supplied by the application: GetFrontText_Ext is nonnull only if
  125. it is appropriate to take input from a front text window - note this
  126. will be null even if the application supports the extension, in the case
  127. where no text file is open at the time this code resource is called.
  128. GetNextFileToSearch_Ext is nonnull if the application supports selecting
  129. multiple files somehow, the most common use being for multi-file
  130. searching. Again this will be passed in as NULL if there are no files
  131. selected at the time of the call.
  132. */
  133. typedef struct InputPopupItems
  134.     {
  135.     short        frontSelected,    /* user's selected text in front text window */
  136.             frontAll,        /* all of text in front window */
  137.             multiSelected,    /* multiple files, as specified within application */
  138.             specificFile;    /* pick one with SFGetFIle */
  139.     } InputPopupItems, *InPopItemPtr;
  140. static InputPopupItems    inPop;
  141.  
  142. /* from AWK_MAIN.C */
  143. extern short AWKmain(short argc, char **argv);
  144.  
  145. /* Functions defined in this file: */
  146. short InvokeHAWK(void); /* the external call - see Code_Main.c */
  147. /* Dialog management, "command line" creation: */
  148. Boolean DoHawkDialog(void);
  149. void CreateHawkProgramResourcePopups(void);
  150. void CreateInputPopup(void);
  151. long FindHawkProgramFolder(char *curvolName, char *hawkFolderName);
  152. void AddProgramsToMenu(char *curvolName, long theDirID, MenuHandle theMenu);
  153. void AlphaAppendMenu(MenuHandle theMenu, short lowPoint, char *name);
  154. short AlphaMenuPos(char *name, MenuHandle theMenu, short highPoint, short lowPoint);
  155. short MenuCompare(char *name, MenuHandle theMenu, short index);
  156. short PtrLenPascalCompare(Ptr spatPtr, short patLen, Ptr stargetPtr);
  157. void DestroyHawkPopups(void);
  158. pascal void HawkPopProc(WindowPtr wdPtr, short item);
  159. pascal void ButtonProc(WindowPtr wdPtr, short item);
  160. void SetPopupMark(short theMenuID, short newItem);
  161. void ResetHS(DialogPtr dPtr);
  162. void LoadHawkDlogFromHS(DialogPtr dPtr, Boolean progToo);
  163. void GetMenuEntryFromFullName(char *name, char *filename);
  164. void SaveInvocation(DialogPtr dPtr, char *name);
  165. Handle CreateHawkProgramResource(DialogPtr dPtr); /* from HS, mostly */
  166. Boolean ReadHAWKResource(char *name); /* to HS */
  167. void ConvertRsrcToHS(Handle h);
  168. void ClearHS(void);
  169. void RedrawItem(DialogPtr dPtr, short itemHit);
  170. void RedrawDialog(DialogPtr dPtr);
  171. Boolean DoVarDialog(DialogPtr hAWKDLOGdPtr);
  172. void LoadExistingVarsToDlog(DialogPtr dPtr);
  173. short BadVarFormat(DialogPtr dPtr);
  174. void GetHawkProgramName(DialogPtr dPtr, short item);
  175. void GetHawkLibraryName(short menuItem);
  176. void GetInputFileName(void);
  177. Boolean GetCommandLineFromDlogResult(void);
  178. char *CreateStdIn(Boolean wholeFile);
  179. Boolean GetInputsFromMFS(void);
  180. /* Error handling, cleanup after run: */
  181. void JumpOnHAWKError(short inputErrorNumber);
  182. void CleanUpAfterHAWK(void);
  183. void HandleHAWKError(void);
  184. void DoExiting(void);
  185.  
  186. short InvokeHAWK(void)
  187.     {
  188.     
  189.     //_fmode = O_TEXT; /* default is binary */
  190.     InitTempCodeMemory(); /* see CodeResource_Helper.c */
  191.     
  192.     if (!DoHawkDialog())
  193.         {
  194.         DoExiting();
  195.         return(-1); /* user cancelled, most likely, or out of memory */
  196.         }
  197.     SetWatchCursor();
  198.     /* If hAWK fails, it long-jumps back to here
  199.     and setjmp returns non-zero. */
  200.     if (!setjmp(envBuf))
  201.         {
  202.         AWKmain(argc, argv);
  203.         CleanUpAfterHAWK();
  204.         //_exiting(1);
  205.         /* show result if wanted */
  206.         DoExiting();
  207.         if (HS.showOut)
  208.             {
  209.             if (HS.selectOut)
  210.                 return(2);
  211.             return(1);
  212.             }
  213.         return(0);
  214.         }
  215.     else
  216.         {
  217.         CleanUpAfterHAWK();
  218.         //_exiting(1);
  219.         HandleHAWKError();
  220.         DoExiting();
  221.         return(-2);
  222.         }
  223.     }
  224.  
  225.  
  226.  
  227. Boolean DoHawkDialog()
  228.     {
  229.     MenuHandle        theMenu;
  230.     DialogPtr        dPtr;
  231.     Handle            theHandle;
  232.     Rect            theBox;
  233.     Point            pt;
  234.     long            aLong;
  235.     short              theID, menuItem;
  236.     short                kind, itemHit, badChar, theType;
  237.     char            mText[64];
  238.     Boolean            checkValue;
  239.     UserItemUPP        HawkPopProcUPP;
  240.     UserItemUPP        ButtonProcUPP;
  241.     
  242.     if (!GetAndAlignDialog(HawkDlogID))
  243.         return(FALSE);
  244.     dPtr = GetNewDialog(HawkDlogID, NULL, (WindowPtr)-1L);
  245.     CreateHawkProgramResourcePopups();
  246.     /* attach procs for popups */
  247.     HawkPopProcUPP = NewUserItemProc(HawkPopProc);
  248.     GetDItem(dPtr, ProgramPopup, &kind, &theHandle, &theBox);
  249.     SetDItem(dPtr,ProgramPopup, kind, (Handle)HawkPopProcUPP, &theBox);
  250.     GetDItem(dPtr, LibraryPopup, &kind, &theHandle, &theBox);
  251.     SetDItem(dPtr,LibraryPopup, kind, (Handle)HawkPopProcUPP, &theBox);
  252.     GetDItem(dPtr, InputPopup, &kind, &theHandle, &theBox);
  253.     SetDItem(dPtr,InputPopup, kind, (Handle)HawkPopProcUPP, &theBox);
  254.     /*...and buttons */
  255.     ButtonProcUPP = NewUserItemProc(ButtonProc);
  256.     GetDItem(dPtr, RunUserItem, &kind, &theHandle, &theBox);
  257.     SetDItem(dPtr,RunUserItem, kind, (Handle)ButtonProcUPP, &theBox);
  258.     GetDItem(dPtr, VarUserItem, &kind, &theHandle, &theBox);
  259.     SetDItem(dPtr,VarUserItem, kind, (Handle)ButtonProcUPP, &theBox);
  260.     ((WindowPeek)(dPtr))->refCon = 0; /* used to record if variables exist */
  261.     /* init HawkSetup */
  262.     HS.progname = HS.inputname = NULL;
  263.     for (itemHit = 0; itemHit < NUMLIBS; ++itemHit)
  264.         HS.libraryname[itemHit] = NULL;
  265.     for (itemHit = 0; itemHit < NUMVARSETS; ++itemHit)
  266.         HS.varsetting[itemHit] = NULL;
  267.     ResetHS(dPtr); /* clears popup contents too */
  268.     SetPopupMark(InputID, HS.inputType);
  269.     ShowWindow(dPtr);
  270.     SetPort(dPtr);
  271.     /* Initially Run and Save Settings are disabled - no program yet */
  272.     HiliteDlgControl(dPtr, 1, 255);
  273.     HiliteDlgControl(dPtr, SaveHawkSetup, 255);
  274.     InitCursor();
  275.     itemHit = 99;
  276.     while (itemHit > 2) /* ie not Run/Cancel */
  277.         {
  278.         ModalDialog(NULL, &itemHit);
  279.         switch (itemHit)
  280.             {
  281.         case SaveHawkSetup: /* enabled only if program has been picked */
  282.             if (HS.progname)
  283.                 SaveInvocation(dPtr, HS.progname);
  284.             /* else very odd error - ignore */
  285.         break;
  286.         case ShowOut:
  287.         case SelectOut:
  288.             GetCheck (dPtr, itemHit, &checkValue);
  289.             SetCheck (dPtr, itemHit, !checkValue);
  290.         break;
  291.         case ProgramPopup:
  292.             /* Treat any pick from this menu as request
  293.             to change main program */
  294.             GetDItem(dPtr, ProgramStat, &kind, &theHandle, &theBox);
  295.             InvertRect(&theBox);
  296.             pt.v = theBox.top;
  297.             pt.h = theBox.right;
  298.             LocalToGlobal(&pt);
  299.             theMenu = GetMHandle(MainProgramID);
  300.             aLong = PopUpMenuSelect(theMenu, pt.v, pt.h, 1);
  301.             theID = HiWord(aLong);
  302.             menuItem = LoWord(aLong);
  303.             InvertRect(&theBox);
  304.             if (menuItem > 0) /* get program and any saved settings */
  305.                 {
  306.                 GetHawkProgramName(dPtr, menuItem);
  307.                 SetPopupMark(InputID, HS.inputType);
  308.                 RedrawDialog(dPtr);
  309.                 }
  310.         break;
  311.         case LibraryPopup:
  312.             /* Either "Select library" - add a library;
  313.             or the name of a library - delete it. */
  314.             GetDItem(dPtr, LibraryStat, &kind, &theHandle, &theBox);
  315.             InvertRect(&theBox);
  316.             pt.v = theBox.top;
  317.             pt.h = theBox.right;
  318.             LocalToGlobal(&pt);
  319.             theMenu = GetMHandle(LibraryID);
  320.             aLong = PopUpMenuSelect(theMenu, pt.v, pt.h, 1);
  321.             theID = HiWord(aLong);
  322.             menuItem = LoWord(aLong);
  323.             InvertRect(&theBox);
  324.             if (menuItem > 0) /* get or delete library */
  325.                 {
  326.                 GetHawkLibraryName(menuItem);
  327.                 RedrawItem(dPtr, itemHit);
  328.                 }
  329.         break;
  330.         case InputPopup:
  331.             GetDItem(dPtr, InputStat, &kind, &theHandle, &theBox);
  332.             InvertRect(&theBox);
  333.             pt.v = theBox.top;
  334.             pt.h = theBox.right;
  335.             LocalToGlobal(&pt);
  336.             theMenu = GetMHandle(InputID);
  337.             aLong = PopUpMenuSelect(theMenu, pt.v, pt.h, HS.inputType);
  338.             theID = HiWord(aLong);
  339.             menuItem = LoWord(aLong);
  340.             InvertRect(&theBox);
  341.             if (menuItem > 0)
  342.                 HS.inputType = menuItem;
  343.             if (menuItem == inPop.frontSelected)
  344.                 {
  345.                 ;
  346.                 }
  347.             else if (menuItem == inPop.frontAll)
  348.                 {
  349.                 ;
  350.                 }
  351.             else if (menuItem == inPop.multiSelected)
  352.                 {
  353.                 ;
  354.                 }
  355.             else if (menuItem == inPop.specificFile)
  356.                 {
  357.                 GetInputFileName();
  358.                 }
  359.             if (menuItem > 0 && menuItem != inPop.specificFile)
  360.                 {
  361.                 if (HS.inputname)
  362.                     {
  363.                     DisposPtr(HS.inputname);
  364.                     HS.inputname = NULL;
  365.                     SetItem(theMenu, inPop.specificFile, (StringPtr)"\pSelect input file...");
  366.                     }
  367.                 }
  368.             if (menuItem > 0)
  369.                 {
  370.                 SetPopupMark(InputID, HS.inputType);
  371.                 RedrawItem(dPtr, itemHit);
  372.                 }
  373.         break;
  374.         case VariableButton:
  375.             if (!DoVarDialog(dPtr)) /* serious error if FALSE */
  376.                 {
  377.                 itemHit = 2;
  378.                 SysBeep(2);
  379.                 goto NeverMind;
  380.                 }
  381.             RedrawDialog(dPtr);
  382.         break;
  383.         case AboutHawk:
  384.             OKStopAlert("Copyright © 1991, Free Software Foundation.\r\
  385. GNU Awk and hAWK come with ABSOLUTELY NO WARRANTY.  This is free software, and \
  386. you are welcome to distribute it under the terms of the GNU General \
  387. Public License, which covers both the warranty information and the \
  388. terms for redistribution.\r\
  389. You should have received a copy of the GNU General Public License along \
  390. with this program (see COPYING hAWK); if not, write to the Free Software Foundation, Inc., \
  391. 675 Mass Ave, Cambridge, MA 02139, USA.");
  392.         break;
  393.             }
  394.         }
  395. NeverMind:
  396.     // TEST ONLY DELETE
  397.     // DisposeRoutineDescriptor(HawkPopProcUPP);
  398.     // DisposeRoutineDescriptor(ButtonProcUPP);
  399.  
  400.     /* cancelled? */
  401.     if (itemHit == 2) /* cancel */
  402.         {
  403.         if (HS.inputname)
  404.             DisposPtr(HS.inputname);
  405.         if (HS.progname)
  406.             DisposPtr(HS.progname);
  407.         for (itemHit = 0; itemHit < NUMLIBS; ++itemHit)
  408.             {
  409.             if (HS.libraryname[itemHit])
  410.                 DisposPtr(HS.libraryname[itemHit]);
  411.             }
  412.         for (itemHit = 0; itemHit < NUMVARSETS; ++itemHit)
  413.             {
  414.             if (HS.varsetting[itemHit])
  415.                 DisposPtr(HS.varsetting[itemHit]);
  416.             }
  417.         DisposDialog(dPtr);
  418.         DestroyHawkPopups();
  419.         return(FALSE);
  420.         }
  421.     /* translate to "commmand" line */
  422.     if(!GetCommandLineFromDlogResult())
  423.         {
  424.         DisposDialog(dPtr);
  425.         DestroyHawkPopups();
  426.         return(FALSE);
  427.         }
  428.     GetCheck (dPtr, ShowOut, &checkValue);
  429.     HS.showOut = checkValue;
  430.     GetCheck (dPtr, SelectOut, &checkValue);
  431.     HS.selectOut = checkValue;
  432.     DisposDialog(dPtr);
  433.     DestroyHawkPopups();
  434.     return(TRUE);
  435.     }
  436.  
  437. /* Called for each run.
  438. The input selection popup depends on what extensions have
  439. been passed in for this run. A largely pointless exercise in
  440. dynamically maintaining a menu, yet Apple disapproves of
  441. disabling items in a popup menu, so this approach has the
  442. virtue of being not-officially-frowned-upon. */
  443. void CreateHawkProgramResourcePopups()
  444.     {
  445.     MenuHandle         theMenu;
  446.     
  447.     CreateInputPopup();
  448.     
  449.     theMenu = NewMenu(LibraryID, (StringPtr)"\pLibraries");
  450.     AppendMenu(theMenu, (StringPtr)"\pSelect library...");
  451.     InsertMenu(theMenu, -1);
  452.     
  453.     theMenu = NewMenu(InputID, (StringPtr)"\pInput");
  454.     if (HasGetFrontText())
  455.         {
  456.         inPop.frontSelected = 1;
  457.         inPop.frontAll = 2;
  458.         AppendMenu(theMenu, (StringPtr)"\pFront text selection");
  459.         AppendMenu(theMenu, (StringPtr)"\pAll of front text");
  460.         }
  461.     else
  462.         {
  463.         inPop.frontSelected = inPop.frontAll = 0;
  464.         }
  465.     if (HasGetNextMultiFile())
  466.         {
  467.         if (inPop.frontSelected)
  468.             inPop.multiSelected = 3;
  469.         else
  470.             inPop.multiSelected = 1;
  471.         AppendMenu(theMenu, (StringPtr)"\pMFS selected files");
  472.         }
  473.     else
  474.         inPop.multiSelected = 0;
  475.     if (inPop.frontSelected || inPop.multiSelected)
  476.         {
  477.         if (inPop.multiSelected == 3) /* all present */
  478.             inPop.specificFile = 5;
  479.         else if (inPop.multiSelected == 1) /* front options missing */
  480.             inPop.specificFile = 3;
  481.         else /* multi missing, therefore hasgetfront */
  482.             inPop.specificFile = 4;
  483.         AppendMenu(theMenu, (StringPtr)"\p-");
  484.         }
  485.     else
  486.         {
  487.         inPop.specificFile = 1;
  488.         }
  489.     /* This option is always available */
  490.     AppendMenu(theMenu, (StringPtr)"\pSelect input file...");
  491.     InsertMenu(theMenu, -1);
  492.     }
  493.  
  494. void CreateInputPopup()
  495.     {
  496.     MenuHandle         theMenu;
  497.     char            curvolName[32];
  498.     long            theDirID;
  499.     
  500.     theMenu = NewMenu(MainProgramID, (StringPtr)"\pMainProgram");
  501.     AppendMenu(theMenu, (StringPtr)"\pSelect unlisted program...");
  502.     
  503.     /* When hAWK is called, the current working folder is the one
  504.     containing hAWK - search it for the folder "hAWK programs.
  505.     If found, add all TEXT files whose names begin with $ to the
  506.     program popup, in alpha order. */
  507.     if (theDirID = FindHawkProgramFolder(curvolName, (char *)"\phAWK programs"))
  508.         AddProgramsToMenu(curvolName, theDirID, theMenu);
  509.     InsertMenu(theMenu, -1);
  510.     }
  511.  
  512. long FindHawkProgramFolder(char *curvolName, char *hawkFolderName)
  513.     {
  514.     HFileInfo    myCPB;
  515.     WDPBRec        theParms;
  516.     char        fName[32];
  517.     long        theDirID;
  518.     short            codeVRefNum, index = 1, len;
  519.     OSErr        err;
  520.     
  521.     
  522.     GetVol(NULL, &codeVRefNum);
  523.     /* Extract "\pVolName:" and dirID for code resource folder */
  524.     theParms.ioNamePtr = (StringPtr)(curvolName);
  525.     theParms.ioVRefNum = codeVRefNum;
  526.     theParms.ioWDIndex = 0;
  527.     theParms.ioWDProcID = 0;
  528.     if (PBGetWDInfo(&theParms,false))
  529.         {
  530.         OKStopAlert("Bad working directory");
  531.         return(0L);
  532.         }
  533.     len = curvolName[0];
  534.     curvolName[len + 1] = ':';
  535.     curvolName[0] = len + 1;
  536.     
  537.     theDirID = theParms.ioWDDirID;
  538.     
  539.     myCPB.ioNamePtr = (StringPtr)fName;
  540.     myCPB.ioVRefNum = theParms.ioWDVRefNum;
  541.     do
  542.         {
  543.         myCPB.ioFDirIndex = index;
  544.         myCPB.ioDirID = theDirID;
  545.         if ((err = PBGetCatInfo((CInfoPBPtr)&myCPB, FALSE)) == noErr)
  546.             {
  547.             if (((myCPB.ioFlAttrib>>4) & 0x01) == 1) /* a folder */
  548.                 {
  549.                 if (PEqualStrs((Byte *)fName, (Byte *)hawkFolderName))
  550.                     return(myCPB.ioDirID);
  551.                 }
  552.             }
  553.         ++index;
  554.         } while (err == noErr);
  555.     /* OKStopAlert("hawk program folder not found"); if you're testing */
  556.     return(0L);
  557.     }
  558.  
  559. void AddProgramsToMenu(char *curvolName, long theDirID, MenuHandle theMenu)
  560.     {
  561.     HFileInfo    myCPB;
  562.     WDPBRec        theParms;
  563.     HVolumeParam    vParms;
  564.     char        fName[32], volName[32];
  565.     short            index = 1, theVolRef, vRefNum;
  566.     OSErr        err;
  567.     Boolean        firstAdd = TRUE;
  568.     
  569.     /* Some shenanigans to open working directory for code resources */
  570.     BlockMove(curvolName, volName, 32);
  571.     vParms.ioCompletion = NULL;
  572.     vParms.ioNamePtr = (StringPtr)(volName);
  573.     vParms.ioVRefNum = -32768;
  574.     vParms.ioVolIndex = -1;
  575.     if (PBHGetVInfo((HParmBlkPtr)&vParms, FALSE))
  576.         theVolRef = 0;
  577.     else
  578.         theVolRef = vParms.ioVRefNum;
  579.     theParms.ioCompletion = NULL;
  580.     theParms.ioVRefNum = theVolRef;
  581.     theParms.ioNamePtr = NULL;
  582.     theParms.ioWDDirID = theDirID;
  583.     theParms.ioWDProcID = 'ERIK';
  584.     if (PBOpenWD(&theParms, FALSE)) /* IM IV pg 158 */
  585.         vRefNum = 0;
  586.     else
  587.         vRefNum = theParms.ioVRefNum;
  588.     
  589.     theParms.ioNamePtr = NULL;
  590.     theParms.ioVRefNum = vRefNum;
  591.     theParms.ioWDIndex = 0;
  592.     theParms.ioWDProcID = 0;
  593.     if (PBGetWDInfo(&theParms,false))
  594.         return;
  595.     HS.defaultVRefNum = vRefNum; /* saved away, folder is left open */
  596.     
  597.     myCPB.ioNamePtr = (StringPtr)fName;
  598.     myCPB.ioVRefNum = theParms.ioWDVRefNum;
  599.     do
  600.         {
  601.         myCPB.ioFDirIndex = index;
  602.         myCPB.ioDirID = theDirID;
  603.         if ((err = PBGetCatInfo((CInfoPBPtr)&myCPB, FALSE)) == noErr)
  604.             {
  605.             if (((myCPB.ioFlAttrib>>4) & 0x01) != 1) /* a file */
  606.                 {
  607.                 /* fName holds name of file */
  608.                 /* Is it the right kind of file? */
  609.                 if (myCPB.ioFlFndrInfo.fdType == 'TEXT'
  610.                     && fName[1] == '$')
  611.                     {
  612.                     if (firstAdd)
  613.                         {
  614.                         AppendMenu(theMenu, (StringPtr)"\p-");
  615.                         AppendMenu(theMenu, (StringPtr)"\p-");
  616.                         firstAdd = FALSE;
  617.                         }
  618.                     AlphaAppendMenu(theMenu, 4, fName);
  619.                     }
  620.                 }
  621.             }
  622.         ++index;
  623.         } while (err == noErr);
  624.     if (firstAdd) /* none added */
  625.         {
  626.         theParms.ioVRefNum = vRefNum;
  627.         PBCloseWD(&theParms, FALSE);
  628.         }
  629.     }
  630.  
  631. void AlphaAppendMenu(MenuHandle theMenu, short lowPoint, char *name)
  632.     {
  633.     short        newItemNum,
  634.             highPoint = CountMItems(theMenu);
  635.     
  636.     
  637.     newItemNum = AlphaMenuPos(name, theMenu, highPoint, lowPoint);
  638.     if (newItemNum > 0)
  639.         {
  640.         /*error duplicate - unlikely for file list. */
  641.         return;
  642.         }
  643.     else
  644.         newItemNum = -newItemNum;
  645.     InsMenuItem(theMenu, (StringPtr)"\pa", newItemNum - 1);
  646.     SetItem(theMenu, newItemNum, (StringPtr)name);
  647.     }
  648.  
  649. /* Binary search existing menu for match against nameptr; if
  650. match return lowPoint:highPoint. If no match let n = where name would
  651. be inserted, range lowPoint:highPoint+1, return -n. For insertion, do
  652. InsMenuItem(theMenu, (StringPtr)"\pa", n - 1); -see just above.
  653. */
  654. short AlphaMenuPos(char *name, MenuHandle theMenu, short highPoint, short lowPoint)
  655.     {
  656.     short        index;
  657.     
  658.     if (highPoint < lowPoint)
  659.         return(-lowPoint);
  660.     
  661.     do
  662.         {
  663.         index = (lowPoint + highPoint)/2;
  664.         if (MenuCompare(name, theMenu, index) < 0)
  665.             highPoint = index - 1;
  666.         else
  667.             lowPoint = index + 1;
  668.         } while (MenuCompare(name, theMenu, index) && lowPoint <= highPoint);
  669.     if (!MenuCompare(name, theMenu, index)) /* a hit */
  670.         return(index);
  671.     /* lowPoint went "one too far", ie it is number that name will be after insertion */
  672.     return(-lowPoint);
  673.     }
  674.  
  675. short MenuCompare(char *name, MenuHandle theMenu, short index)
  676.     {
  677.     char            itemStr[64];
  678.     
  679.     GetItem(theMenu, index, (StringPtr)itemStr);
  680.     /* Fudge, both mark and item strs are pascal, but warp to ptr/len vs pascal.
  681.     Sorry folks, doing it this way because I had the tested code already. */
  682.     return(PtrLenPascalCompare(name + 1L, name[0], itemStr));
  683.     }
  684.  
  685. /* Compare, for ptr, len vs pascal strings.
  686. Compare pattern with target, returning number
  687. reflecting alphabetical rather than ascii order.
  688. */
  689. typedef Byte *BPtr;
  690. short PtrLenPascalCompare(Ptr spatPtr, short patLen, Ptr stargetPtr)
  691.     {
  692.     BPtr    patPtr = (BPtr)spatPtr,
  693.             patEndPtr = patPtr + patLen,
  694.             curPtr = (BPtr)stargetPtr + 1,
  695.             curEndPtr = curPtr + (unsigned short)(stargetPtr[0]);
  696.     short        i, j;
  697.     
  698.     while (patPtr < patEndPtr && curPtr < curEndPtr && *patPtr == *curPtr)
  699.         {
  700.         ++patPtr;
  701.         ++curPtr;
  702.         }
  703.     
  704.     if (patPtr == patEndPtr && curPtr == curEndPtr) /* exact match */
  705.         return(0);
  706.     if (patPtr == patEndPtr && curPtr != curEndPtr) /* pattern too short */
  707.         return(-1);
  708.     if (patPtr != patEndPtr && curPtr == curEndPtr) /* starget too short */
  709.         return(1);
  710.     
  711.     /* true miscompare within string */
  712.     i = (short)*patPtr;
  713.     j = (short)*curPtr;
  714.     /* sequence: nonalpha, AaBbCc...Zz */
  715.     /* 'A' = 65, 'a' = 97; move 'U' to 'U'*2 + 256, 'u' to 'u'*2 + 193 */
  716.     /* 'A' -> 386, 'B' -> 388, 'a' -> 387, 'b' -> 389 etc */
  717.     if ('A' <= i && i <= 'Z')
  718.         i = i*2 + 256;
  719.     else if ('a' <= i && i <= 'z')
  720.         i = i*2 + 193;
  721.     if ('A' <= j && j <= 'Z')
  722.         j = j*2 + 256;
  723.     else if ('a' <= j && j <= 'z')
  724.         j = j*2 + 193;
  725.     return(i - j);
  726.     }
  727.  
  728. void DestroyHawkPopups()
  729.     {
  730.     MenuHandle    theMenu;
  731.     
  732.     theMenu = GetMHandle(MainProgramID);
  733.     if (!theMenu)
  734.         return;
  735.     DeleteMenu(MainProgramID);
  736.     DisposeMenu(theMenu);
  737.     
  738.     theMenu = GetMHandle(LibraryID);
  739.     if (!theMenu)
  740.         return;
  741.     DeleteMenu(LibraryID);
  742.     DisposeMenu(theMenu);
  743.     
  744.     theMenu = GetMHandle(InputID);
  745.     if (!theMenu)
  746.         return;
  747.     DeleteMenu(InputID);
  748.     DisposeMenu(theMenu);
  749.     }
  750.  
  751. /* Somebody's watching, so draw in the popup menus. */
  752. pascal void HawkPopProc(WindowPtr wdPtr, short item)
  753.     {
  754.     GrafPtr        savePort;
  755.     short            kind, menuNum, i, n, markChar;
  756.     Handle        theHandle;
  757.     MenuHandle    theMenu;
  758.     Rect        box;
  759.     Byte        mText[64];
  760.     
  761.     GetPort(&savePort);
  762.     SetPort (wdPtr);
  763.     if (item == LibraryPopup)
  764.         {
  765.         theMenu = GetMHandle(LibraryID);
  766.         menuNum = 1;
  767.         }
  768.     else if (item == ProgramPopup || item == InputPopup)
  769.         {
  770.         if (item == ProgramPopup)
  771.             theMenu = GetMHandle(MainProgramID);
  772.         else
  773.             theMenu = GetMHandle(InputID);
  774.         n = CountMItems(theMenu);
  775.         for (i = 1; i <= n; ++i)
  776.             {
  777.             GetItemMark(theMenu, i, &markChar);
  778.             if (markChar == ' ')
  779.                 break;
  780.             }
  781.         if (i <= n)
  782.             menuNum = i;
  783.         else
  784.             menuNum = 1;
  785.         }
  786.     else return;
  787.     
  788.     GetDItem(wdPtr, item, &kind, &theHandle, &box);
  789.     GetItem(theMenu, menuNum, mText);
  790.     EraseRect(&box);
  791.     TextBox(&(mText[1]),(unsigned char)(mText[0]),&box,teJustLeft);
  792.     box.left -= 1;
  793.     box.top -= 1;
  794.     box.right += 1;
  795.     box.bottom += 1;
  796.     FrameRect(&box);
  797.     MoveTo(box.left + 1, box.bottom);
  798.     LineTo(box.right, box.bottom);
  799.     MoveTo(box.right, box.top + 1);
  800.     LineTo(box.right, box.bottom);
  801.     SetPort(savePort);
  802.     }
  803.  
  804. pascal void ButtonProc(WindowPtr wdPtr, short item)
  805.     {
  806.     GrafPtr            savePort;
  807.     PenState        savePen;
  808.     Handle           h;
  809.     Rect            theBox;
  810.     short                theType, ovalSize, i;
  811.     Pattern            myWhite, myGray;
  812.     Boolean            needsFrame;
  813.     
  814.     GetDItem(wdPtr,item,&theType,&h,&theBox);
  815.     GetPort(&savePort);
  816.     SetPort(wdPtr);
  817.     GetPenState(&savePen);
  818.     PenNormal();
  819.     PenSize(2,2);
  820.     if (item == RunUserItem)
  821.         InsetRect(&theBox,-3,-3);
  822.     else if (item == VarUserItem)
  823.         {
  824.         needsFrame =(Boolean)(((WindowPeek)(wdPtr))->refCon);
  825.         if (needsFrame)
  826.             {
  827.             for (i = 0; i < 8; i += 2)
  828.                 myGray.pat[i] = 0xAA;
  829.             for (i = 1; i < 8; i += 2)
  830.                 myGray.pat[i] = 0x55;
  831.             PenPat(&myGray);
  832.             }
  833.         else
  834.             {
  835.             for (i = 0; i < 8; ++i)
  836.                 myWhite.pat[i] = 0;
  837.             PenPat(&myWhite);
  838.             }
  839.         InsetRect(&theBox,-2,-2);
  840.         
  841.         }
  842.     ovalSize = (theBox.bottom + 8 - theBox.top) / 2;    
  843.     FrameRoundRect(&theBox,ovalSize,ovalSize);
  844.     SetPenState(&savePen);
  845.     SetPort(savePort);
  846.     }
  847.  
  848. /* A space character is used to mark the currently-selected item,
  849. avoiding the horror of attempting to access global variables
  850. within the pascal callback above, within a CODE resource. */
  851. void SetPopupMark(short theMenuID, short newItem)
  852.     {
  853.     short            i, n, markChar;
  854.     MenuHandle    theMenu;
  855.     
  856.     theMenu = GetMHandle(theMenuID);
  857.     n = CountMItems(theMenu);
  858.     for (i = 1; i <= n; ++i)
  859.         {
  860.         GetItemMark(theMenu, i, &markChar);
  861.         if (markChar == ' ')
  862.             {
  863.             if (i == newItem)
  864.                 return;
  865.             else
  866.                 SetItemMark(theMenu, i, 0);
  867.             }
  868.         else if (i == newItem)
  869.             {
  870.             markChar = ' ';
  871.             SetItemMark(theMenu, i, markChar);
  872.             }
  873.         }
  874.     }
  875.  
  876. void ResetHS(DialogPtr dPtr)
  877.     {
  878.     MenuHandle    theMenu;
  879.     short        itemHit, numItems;
  880.     
  881.     SetCheck (dPtr, ShowOut, TRUE);
  882.     SetCheck (dPtr, SelectOut, TRUE);
  883.     mainProgMenuNum = libraryMenuNum = HS.inputType = 1;
  884.     HS.showOut = TRUE;
  885.     HS.selectOut = TRUE;
  886.     if (HS.progname)
  887.         {
  888.         DisposPtr(HS.progname);
  889.         HS.progname = NULL;
  890.         }
  891.     if (HS.inputname)
  892.         {
  893.         DisposPtr(HS.inputname);
  894.         HS.inputname = NULL;
  895.         }
  896.     for (itemHit = 0; itemHit < NUMLIBS; ++itemHit)
  897.         {
  898.         if (HS.libraryname[itemHit])
  899.             {
  900.             DisposPtr(HS.libraryname[itemHit]);
  901.             HS.libraryname[itemHit] = NULL;
  902.             }
  903.         }
  904.     for (itemHit = 0; itemHit < NUMVARSETS; ++itemHit)
  905.         {
  906.         if (HS.varsetting[itemHit])
  907.             {
  908.             DisposPtr(HS.varsetting[itemHit]);
  909.             HS.varsetting[itemHit] = NULL;
  910.             }
  911.         }
  912.     theMenu = GetMHandle(MainProgramID);
  913.     SetItem(theMenu, 1, (StringPtr)"\pSelect unlisted program...");
  914.     theMenu = GetMHandle(LibraryID);
  915.     itemHit = CountMItems(theMenu);
  916.     while (--itemHit > 0)
  917.         DelMenuItem(theMenu, 1);
  918.     theMenu = GetMHandle(InputID);
  919.     SetItem(theMenu, inPop.specificFile, (StringPtr)"\pSelect input file...");
  920.     }
  921.  
  922. /* Set visual display and menus in Hawk dialog, and at end
  923. convert all strings from pascal to c format. Note vars are not
  924. shown here (but their strings are converted).
  925. Assumes menus have been reset.
  926. If progToo is FALSE, being called in response to HawkDlog main program popup
  927. which retrieves and sets progname directly from open dialog, and also
  928. sets menu entry. If progToo is TRUE, then have received progname from resource
  929. and should then handle progname here - currently not needed.
  930.  */
  931. void LoadHawkDlogFromHS(DialogPtr dPtr, Boolean progToo)
  932.     {
  933.     MenuHandle    theMenu;
  934.     short            i, numItems = 1;
  935.     char        filename[32];
  936.     
  937.     /* Set the checks */
  938.     SetCheck (dPtr, ShowOut, HS.showOut);
  939.     SetCheck (dPtr, SelectOut, HS.selectOut);
  940.     
  941.     if (progToo)
  942.         {
  943.         PtoCstr((StringPtr)HS.progname);
  944.         GetMenuEntryFromFullName(HS.progname, filename);
  945.         theMenu = GetMHandle(MainProgramID);
  946.         SetItem(theMenu, 1, (StringPtr)filename);
  947.         }
  948.     /* variables - nothing shown, just convert strings */
  949.     for (i = 0; i < NUMVARSETS; ++i)
  950.         {
  951.         if (HS.varsetting[i])
  952.             PtoCstr((StringPtr)HS.varsetting[i]);
  953.         else
  954.             break;
  955.         }
  956.     /* dialog's refCon used to tell ButtonProc if variables exist */
  957.     if (i)
  958.         ((WindowPeek)(dPtr))->refCon = 1;
  959.     else
  960.         ((WindowPeek)(dPtr))->refCon = 0;
  961.     /* libraries - append to menu and convert strings */
  962.     theMenu = GetMHandle(LibraryID);
  963.     for (i = 0; i < NUMLIBS; ++i)
  964.         {
  965.         if (HS.libraryname[i])
  966.             {
  967.             PtoCstr((StringPtr)HS.libraryname[i]);
  968.             GetMenuEntryFromFullName(HS.libraryname[i], filename);
  969.             if (numItems == 1)
  970.                 {
  971.                 InsMenuItem(theMenu, (StringPtr)"\pa", 0);
  972.                 SetItem(theMenu, 1, (StringPtr)filename);
  973.                 InsMenuItem(theMenu, (StringPtr)"\p-", 1);
  974.                 }
  975.             else
  976.                 {
  977.                 InsMenuItem(theMenu, (StringPtr)"\pa", numItems-2);
  978.                 SetItem(theMenu, numItems-1, (StringPtr)filename);
  979.                 }
  980.             ++numItems;
  981.             
  982.             }
  983.         else
  984.             break;
  985.         }
  986.     /* input - set input file name */
  987.     if (HS.inputType == inPop.specificFile)
  988.         {
  989.         if (HS.inputname)
  990.             {
  991.             PtoCstr((StringPtr)HS.inputname);
  992.             GetMenuEntryFromFullName(HS.inputname, filename);
  993.             if (filename[0])
  994.                 {
  995.                 theMenu = GetMHandle(InputID);
  996.                 SetItem(theMenu, inPop.specificFile, (StringPtr)filename);
  997.                 }
  998.             }
  999.         }
  1000.     }
  1001.  
  1002. /* Extract pstr filename from end of cstr full path name */
  1003. void GetMenuEntryFromFullName(char *name, char *filename)
  1004.     {
  1005.     short len = strlen(name);
  1006.     Ptr    endPtr = name + len, startPtr = endPtr ;
  1007.     
  1008.     while (startPtr >= name)
  1009.         {
  1010.         if (*startPtr == ':')
  1011.             break;
  1012.         --startPtr;
  1013.         }
  1014.     ++startPtr;
  1015.     if (startPtr >= endPtr)
  1016.         {
  1017.         filename[0] = 0;
  1018.         return;
  1019.         }
  1020.     filename[0] = endPtr - startPtr;
  1021.     BlockMove(startPtr, filename+1, filename[0]);
  1022.     }
  1023.  
  1024. void SaveInvocation(DialogPtr dPtr, char *name)
  1025.     {
  1026.     short         saveVol, refNum, vRefNum;
  1027.     Handle        rHdle;
  1028.     char         filename[32];
  1029.     short         len = strlen(name);
  1030.     Ptr            endPtr = name + len, startPtr = endPtr ;
  1031.     
  1032.     while (startPtr >= name)
  1033.         {
  1034.         if (*startPtr == ':')
  1035.             break;
  1036.         --startPtr;
  1037.         }
  1038.     ++startPtr;
  1039.     if (startPtr >= endPtr) return;
  1040.     filename[0] = endPtr - startPtr;
  1041.     BlockMove(startPtr, filename+1, filename[0]);
  1042.     
  1043.     vRefNum = HS.progVRefNum;
  1044.     if (!vRefNum) return;
  1045.     
  1046.     if (GetVol(NULL, &saveVol))
  1047.         saveVol = 0;
  1048.  
  1049.     SetVol(NULL, vRefNum);
  1050.     if (refNum = OpenOrCreateResourceFork((StringPtr)filename))
  1051.         {
  1052.         if (rHdle = CreateHawkProgramResource(dPtr))
  1053.             {
  1054.             DeleteAllExistingRsrcs('HAWK', HAWKID);
  1055.             AddResource(rHdle, 'HAWK', HAWKID, (StringPtr)"");
  1056.             }
  1057.         CloseResFile (refNum);
  1058.         }
  1059.     /* Reset volume to original one */
  1060.     if (saveVol)
  1061.         SetVol(NULL, saveVol);
  1062.     /* Make sure changes are written out */
  1063.     FlushVol(NULL, vRefNum);
  1064.     }
  1065.  
  1066. /* Note all strings are c strings coming in (and going out).
  1067. Only HS.inputType requires special attention: it is the menu
  1068. item number corresponding to the currently-selected input
  1069. option, and varies according to which extensions from the
  1070. calling application have currently been made available. To avoid
  1071. confusion, the number saved is the one that would be used if all
  1072. extensions were present. */
  1073. Handle CreateHawkProgramResource(DialogPtr dPtr)
  1074.     {
  1075.     Handle    resH;
  1076.     Ptr        tPtr;
  1077.     long    size;
  1078.     short        numLibs = 0, numVars = 0, i, len;
  1079.     
  1080.     if (!(HS.progname)) return(NULL);
  1081.     /* precalc size of handle */
  1082.     size = 8;
  1083.     size += strlen(HS.progname) + 1;
  1084.     for (i = 0; i <= NUMLIBS; ++i)
  1085.         {
  1086.         if (!(HS.libraryname[i]))
  1087.             break;
  1088.         size += strlen(HS.libraryname[i]) + 1;
  1089.         ++numLibs;
  1090.         }
  1091.     for (i = 0; i < NUMVARSETS; ++i)
  1092.         {
  1093.         if (!(HS.varsetting[i]))
  1094.             break;
  1095.         size += strlen(HS.varsetting[i]) + 1;
  1096.         ++numVars;
  1097.         }
  1098.     if (HS.inputType == inPop.specificFile)
  1099.         size += strlen(HS.inputname) + 1;
  1100.     
  1101.     GetCheck(dPtr, ShowOut, &(HS.showOut));
  1102.     GetCheck(dPtr, SelectOut, &(HS.selectOut));
  1103.     
  1104.     resH = NewHandle(size);
  1105.     if (MemError() != noErr)
  1106.         return(NULL);
  1107.     tPtr = *resH;
  1108.     len = HS.inputType;
  1109.     if (inPop.specificFile < 5) /* adjust recorded input type */
  1110.         {
  1111.         /* Boost value of HS.inputType to what it would be if all
  1112.         input options were present - here we know that either the two
  1113.         front text options or the multifile option or both are missing. */
  1114.         if (HS.inputType == 1)
  1115.             {
  1116.             if (inPop.frontSelected == 0 && inPop.multiSelected == 0)
  1117.                 HS.inputType = 5;
  1118.             else if (inPop.frontSelected == 0)
  1119.                 HS.inputType = 3;
  1120.             else
  1121.                 HS.inputType = 1;
  1122.             }
  1123.         else if (HS.inputType == 3) /* implies inPop.frontSelected == 0 */
  1124.             HS.inputType = 5;
  1125.         else if (HS.inputType == 4) /* implies inPop.multiSelected == 0 */
  1126.             HS.inputType = 5;
  1127.         /* note HS.inputType == 2 needs no adjusting */
  1128.         }
  1129.     BlockMove((Ptr)(&HS.inputType), tPtr, 2);
  1130.     HS.inputType = len;
  1131.     tPtr += 2;
  1132.     BlockMove((Ptr)(&HS.showOut), tPtr, 1);
  1133.     ++tPtr;
  1134.     BlockMove((Ptr)(&HS.selectOut), tPtr, 1);
  1135.     ++tPtr;
  1136.     BlockMove((Ptr)(&numLibs), tPtr, 2);
  1137.     tPtr += 2;
  1138.     BlockMove((Ptr)(&numVars), tPtr, 2);
  1139.     tPtr += 2;
  1140.     /* Save text items in pascal format for easier read/write/setup */
  1141.     len = strlen(HS.progname);
  1142.     *tPtr++ = len;
  1143.     BlockMove(HS.progname, tPtr, len);
  1144.     tPtr += len;
  1145.     for (i = 0; i < NUMLIBS; ++i)
  1146.         {
  1147.         if (!(HS.libraryname[i]))
  1148.             break;
  1149.         len = strlen(HS.libraryname[i]);
  1150.         *tPtr++ = len;
  1151.         BlockMove(HS.libraryname[i], tPtr, len);
  1152.         tPtr += len;
  1153.         }
  1154.     for (i = 0; i < NUMVARSETS; ++i)
  1155.         {
  1156.         if (!(HS.varsetting[i]))
  1157.             break;
  1158.         len = strlen(HS.varsetting[i]);
  1159.         *tPtr++ = len;
  1160.         BlockMove(HS.varsetting[i], tPtr, len);
  1161.         tPtr += len;
  1162.         }
  1163.     if (HS.inputType == inPop.specificFile)
  1164.         {
  1165.         len = strlen(HS.inputname);
  1166.         *tPtr++ = len;
  1167.         BlockMove(HS.inputname, tPtr, len);
  1168.         }
  1169.     return(resH);
  1170.     }
  1171.  
  1172. /* Open res fork of Hawk pgm, copy setup info to HS. */
  1173. Boolean ReadHAWKResource(char *name) /* to HS */
  1174.     {
  1175.     short         saveVol, refNum, vRefNum;
  1176.     Handle        rHdle;
  1177.     char         filename[32];
  1178.     short         len = strlen(name);
  1179.     Ptr            endPtr = name + len, startPtr = endPtr ;
  1180.     
  1181.     while (startPtr >= name)
  1182.         {
  1183.         if (*startPtr == ':')
  1184.             break;
  1185.         --startPtr;
  1186.         }
  1187.     ++startPtr;
  1188.     if (startPtr >= endPtr) return(FALSE);
  1189.     filename[0] = endPtr - startPtr;
  1190.     BlockMove(startPtr, filename+1, filename[0]);
  1191.     
  1192.     vRefNum = HS.progVRefNum;
  1193.     if (!vRefNum) return(FALSE);
  1194.     
  1195.     if (GetVol(NULL, &saveVol))
  1196.         saveVol = 0;
  1197.     SetVol(NULL, vRefNum);
  1198.     
  1199.     if ((refNum = OpenResFile((StringPtr)filename)) != -1)
  1200.         {
  1201.         rHdle = Get1Resource ('HAWK', HAWKID);
  1202.         if (!rHdle)
  1203.             {
  1204.             CloseResFile(refNum);
  1205.             if (saveVol)
  1206.                 SetVol(NULL, saveVol);
  1207.             return(FALSE);
  1208.             }
  1209.         /* Convert raw rsrc to HS */
  1210.         ConvertRsrcToHS(rHdle);
  1211.         ReleaseResource(rHdle);
  1212.         CloseResFile(refNum);
  1213.         }
  1214.     /* Restore default volume if any */
  1215.     if (saveVol)
  1216.         SetVol(NULL, saveVol);
  1217.     if (refNum == -1)
  1218.         return(FALSE);
  1219.     return(TRUE);
  1220.     }
  1221.  
  1222. /* Retrieve HawkSetup data, with strings in pascal format for the moment.
  1223. Set progname only if it has not already been set.
  1224. HS.inputType was saved as though all extensions present - if 
  1225. currently some extensions are missing then inputType needs adjusting.
  1226. The default for a missing choice is inPop.specificFile. */
  1227. void ConvertRsrcToHS(Handle h)
  1228.     {
  1229.     Ptr        tPtr, endPtr;
  1230.     long    size;
  1231.     short        numLibs, numVars, i, len, recordedInputType;
  1232.     
  1233.     //MoveHHi(h);
  1234.     HLock(h);
  1235.     tPtr = *h;
  1236.     size = GetHandleSize(h);
  1237.     endPtr = tPtr + size;
  1238.     BlockMove(tPtr, (Ptr)(&HS.inputType), 2);
  1239.     recordedInputType = HS.inputType;
  1240.     /* adjust inputType if extension(s) missing */
  1241.     if (inPop.specificFile < 5) /* adjust input type */
  1242.         {
  1243.         if (HS.inputType == 1 || HS.inputType == 2)
  1244.             {
  1245.             /* the frontSelected/frontAll options, not valid if 
  1246.             inPop.frontSelected == 0 */
  1247.             if (inPop.frontSelected == 0)
  1248.                 HS.inputType = inPop.specificFile;
  1249.             }
  1250.         else if (HS.inputType == 3)
  1251.             {
  1252.             /* multiSelected option - not valid if inPop.multiSelected == 0,
  1253.             and adjust if inPop.frontSelected == 0 */
  1254.             if (inPop.multiSelected == 0)
  1255.                 HS.inputType = inPop.specificFile;
  1256.             else if (inPop.frontSelected == 0)
  1257.                 HS.inputType = inPop.multiSelected;
  1258.             }
  1259.         else if (HS.inputType == 5) /* always valid */
  1260.             {
  1261.             if (inPop.frontSelected == 0 && inPop.multiSelected == 0)
  1262.                 HS.inputType = 1;
  1263.             else if (inPop.frontSelected == 0)
  1264.                 HS.inputType = 3;
  1265.             else
  1266.                 HS.inputType = 4;
  1267.             }
  1268.         /* note  4 not possible - in the full menu it's a dashed line */
  1269.         }
  1270.     tPtr += 2;
  1271.     BlockMove(tPtr, (Ptr)(&HS.showOut), 1);
  1272.     ++tPtr;
  1273.     BlockMove(tPtr, (Ptr)(&HS.selectOut), 1);
  1274.     ++tPtr;
  1275.     BlockMove(tPtr, (Ptr)(&numLibs), 2);
  1276.     tPtr += 2;
  1277.     BlockMove(tPtr, (Ptr)(&numVars), 2);
  1278.     tPtr += 2;
  1279.     len = *tPtr++;
  1280.     if (tPtr + len > endPtr)
  1281.         goto NoGo;
  1282.     if (!(HS.progname))
  1283.         {
  1284.         HS.progname = NewPtr(len+1);
  1285.         if (MemError() != noErr)
  1286.             goto NoGo;
  1287.         HS.progname[0] = len;
  1288.         BlockMove(tPtr, HS.progname+1, len);
  1289.         }
  1290.     tPtr += len;
  1291.     for (i = 0; i < numLibs; ++i)
  1292.         {
  1293.         len = *tPtr++;
  1294.         if (tPtr + len > endPtr)
  1295.             goto NoGo;
  1296.         HS.libraryname[i] = NewPtr(len+1);
  1297.         if (MemError() != noErr)
  1298.             goto NoGo;
  1299.         HS.libraryname[i][0] = len;
  1300.         BlockMove(tPtr, HS.libraryname[i]+1, len);
  1301.         tPtr += len;
  1302.         }
  1303.     for (i = 0; i < numVars; ++i)
  1304.         {
  1305.         len = *tPtr++;
  1306.         if (tPtr + len > endPtr)
  1307.             goto NoGo;
  1308.         HS.varsetting[i] = NewPtr(len+1);
  1309.         if (MemError() != noErr)
  1310.             goto NoGo;
  1311.         HS.varsetting[i][0] = len;
  1312.         BlockMove(tPtr, HS.varsetting[i]+1, len);
  1313.         tPtr += len;
  1314.         }
  1315.     if (recordedInputType == 5)
  1316.         {
  1317.         len = *tPtr++;
  1318.         if (tPtr + len > endPtr)
  1319.             goto NoGo;
  1320.         HS.inputname = NewPtr(len+1);
  1321.         if (MemError() != noErr)
  1322.             goto NoGo;
  1323.         HS.inputname[0] = len;
  1324.         BlockMove(tPtr, HS.inputname+1, len);
  1325.         }
  1326.     HUnlock(h);
  1327.     return;
  1328. NoGo:
  1329.     HUnlock(h);
  1330.     ClearHS();
  1331.     return;
  1332.     }
  1333.  
  1334. void ClearHS()
  1335.     {
  1336.     short        itemHit;
  1337.     
  1338.     HS.showOut = TRUE;
  1339.     HS.selectOut = TRUE;
  1340.     if (HS.inputname)
  1341.         {
  1342.         DisposPtr(HS.inputname);
  1343.         HS.inputname = NULL;
  1344.         }
  1345.     for (itemHit = 0; itemHit < NUMLIBS; ++itemHit)
  1346.         {
  1347.         if (HS.libraryname[itemHit])
  1348.             {
  1349.             DisposPtr(HS.libraryname[itemHit]);
  1350.             HS.libraryname[itemHit] = NULL;
  1351.             }
  1352.         }
  1353.     for (itemHit = 0; itemHit < NUMVARSETS; ++itemHit)
  1354.         {
  1355.         if (HS.varsetting[itemHit])
  1356.             {
  1357.             DisposPtr(HS.varsetting[itemHit]);
  1358.             HS.varsetting[itemHit] = NULL;
  1359.             }
  1360.         }
  1361.     }
  1362.  
  1363. void RedrawItem(DialogPtr dPtr, short itemHit)
  1364.     {
  1365.     GrafPtr        savePort;
  1366.     short            kind;
  1367.     Handle        theHandle;
  1368.     MenuHandle    theMenu;
  1369.     Rect        box;
  1370.     
  1371.     GetPort(&savePort);
  1372.     SetPort (dPtr);
  1373.     GetDItem(dPtr, itemHit, &kind, &theHandle, &box);
  1374.     InvalRect(&box);
  1375.     SetPort(savePort);
  1376.     }
  1377.  
  1378. void RedrawDialog(DialogPtr dPtr)
  1379.     {
  1380.     GrafPtr        savePort;
  1381.     
  1382.     GetPort(&savePort);
  1383.     SetPort (dPtr);
  1384.     InvalRect(&dPtr->portRect);
  1385.     SetPort(savePort);
  1386.     }
  1387.  
  1388. #define VARDlog        407
  1389. #define FirstVARID    4
  1390.  
  1391. /* The variables dialog. Needs a bit more error-checking. */
  1392. Boolean DoVarDialog(DialogPtr hAWKDLOGdPtr)
  1393.     {
  1394.     DialogPtr        dPtr;
  1395.     short                itemHit, theType, i, j;
  1396.     char            varStr[100];
  1397.     
  1398.     if (!GetAndAlignDialog(VARDlog))
  1399.         return(FALSE);
  1400.     dPtr = GetNewDialog(VARDlog, NULL, (WindowPtr)-1L);
  1401.     LoadExistingVarsToDlog(dPtr);
  1402.     ShowWindow(dPtr);
  1403.     FrameDialogItem(dPtr,1);
  1404.     InitCursor();
  1405.     itemHit = 99;
  1406.     while (itemHit > 2)
  1407.         {
  1408.         ModalDialog(NULL, &itemHit);
  1409.         /* Check length if you think someone might type > 99 characters */
  1410.         if (itemHit == 1) /* check format */
  1411.             {
  1412.             if ((itemHit = BadVarFormat(dPtr)) > 3)
  1413.                 {
  1414.                 SysBeep(2);
  1415.                 SelIText(dPtr, itemHit, 0, 32767);
  1416.                 }
  1417.             }
  1418.         }
  1419.     if (itemHit == 2) /* cancel */
  1420.         {
  1421.         DisposDialog(dPtr);
  1422.         return(TRUE);
  1423.         }
  1424.     /* Record new variable settings */
  1425.     j = 0;
  1426.     for (i = FirstVARID; i < FirstVARID + NUMVARSETS; ++i)
  1427.         {
  1428.         GetEText(dPtr, i, (StringPtr) varStr);
  1429.         if (varStr[0])
  1430.             {
  1431.             HS.varsetting[j] = NewPtr(varStr[0] + 3);
  1432.             if (MemError() != noErr)
  1433.                 return(FALSE);
  1434.             HS.varsetting[j][0] = varStr[0] + 2;
  1435.             BlockMove(varStr+1, HS.varsetting[j] + 3, varStr[0]);
  1436.             /* stick -v in front */
  1437.             HS.varsetting[j][1] = '-';
  1438.             HS.varsetting[j][2] = 'v';
  1439.             PtoCstr((StringPtr)HS.varsetting[j]);
  1440.             ++j;
  1441.             }
  1442.         }
  1443.     /* dialog's refCon used to tell ButtonProc if variables exist */
  1444.     if (j)
  1445.         ((WindowPeek)(hAWKDLOGdPtr))->refCon = 1;
  1446.     else
  1447.         ((WindowPeek)(hAWKDLOGdPtr))->refCon = 0;
  1448.     /* null out any left over */
  1449.     while (j < NUMVARSETS)
  1450.         {
  1451.         HS.varsetting[j++] = NULL;
  1452.         }
  1453.     DisposDialog(dPtr);
  1454.     return(TRUE);
  1455.     }
  1456.  
  1457. void LoadExistingVarsToDlog(DialogPtr dPtr)
  1458.     {
  1459.     short        itemHit;
  1460.     
  1461.     /* set the fields before showing */
  1462.     for (itemHit = 0; itemHit < NUMVARSETS; ++itemHit)
  1463.         {
  1464.         if (HS.varsetting[itemHit] && strlen(HS.varsetting[itemHit]))
  1465.             {
  1466.             /* Minor complication - have -v in front */
  1467.             CtoPstr(HS.varsetting[itemHit]+2);
  1468.             SetEText(dPtr, FirstVARID + itemHit, 
  1469.                 (StringPtr) (HS.varsetting[itemHit]+2));
  1470.             PtoCstr((StringPtr)HS.varsetting[itemHit]+2);
  1471.             }
  1472.         else
  1473.             SetEText(dPtr, FirstVARID + itemHit, 
  1474.                 (StringPtr) "\p");
  1475.         }
  1476.     }
  1477.  
  1478. /* Return 1 if all vars OK, var item number if one is bad (>= 4) */
  1479. short BadVarFormat(DialogPtr dPtr)
  1480.     {
  1481.     short                i, j, len;
  1482.     char            varStr[100];
  1483.     
  1484.     /* Variable format is varname=something. This is a quick check. */
  1485.     for (i = FirstVARID; i < FirstVARID + NUMVARSETS; ++i)
  1486.         {
  1487.         GetEText(dPtr, i, (StringPtr) varStr);
  1488.         if (varStr[0])
  1489.             {
  1490.             len = varStr[0];
  1491.             for (j = 1; j <= len; ++j)
  1492.                 {
  1493.                 if (varStr[j] == '=')
  1494.                     break;
  1495.                 }
  1496.             if (j >= len || j == 1)
  1497.                 return(i);
  1498.             }
  1499.         }
  1500.     return(1);
  1501.     }
  1502.  
  1503. void GetHawkProgramName(DialogPtr dPtr, short item)
  1504.     {
  1505.     MenuHandle    theMenu;
  1506.     Point         where;
  1507.     SFReply     reply;
  1508.     SFTypeList     types;
  1509.     long        len;
  1510.     short            numTypes;
  1511.     Boolean        userLocated;
  1512.     
  1513.     if (item == 1)
  1514.         {
  1515.         /* display dialog, get program name and input file name */
  1516.         types[0] = 'TEXT';
  1517.         types[1] = 'RRRS';
  1518.         numTypes = 2;
  1519.         GetDlogOrigin (getDlgID, &where);
  1520.         SFGetFile (where, (StringPtr)"\p", NULL, numTypes, types, NULL, &reply);
  1521.         if (!reply.good)
  1522.             return;
  1523.         userLocated = TRUE;
  1524.         }
  1525.     else /* either listed or unlisted program - the unlisted one is number 3 */
  1526.         {
  1527.         if (item == mainProgMenuNum) /* nothing new */
  1528.             return;
  1529.         theMenu = GetMHandle(MainProgramID);
  1530.         GetItem(theMenu, item, (StringPtr)(reply.fName));
  1531.         userLocated = FALSE;
  1532.         }
  1533.     /* reset HS and dialog */
  1534.     ResetHS(dPtr);
  1535.     
  1536.     HS.progname = NewPtr(256);
  1537.     if (MemError() != noErr)
  1538.         {
  1539.         HS.progVRefNum = 0;
  1540.         MemoryAlert();
  1541.         HiliteDlgControl(dPtr, 1, 255);
  1542.         HiliteDlgControl(dPtr, SaveHawkSetup, 255);
  1543.         return;
  1544.         }
  1545.     if (userLocated)
  1546.         HS.progVRefNum = reply.vRefNum;
  1547.     else if (item == 3)
  1548.         HS.progVRefNum = HS.otherVRefNum;
  1549.     else
  1550.         HS.progVRefNum = HS.defaultVRefNum;
  1551.     if (userLocated)
  1552.         mainProgMenuNum = 3;
  1553.     else
  1554.         mainProgMenuNum = item;
  1555.     AppendPStr((Byte *)(FullPathNameFromVRefNum(HS.progVRefNum,(Byte *)(HS.progname))),
  1556.         (Byte *)(reply.fName));
  1557.     /* stick -f in front */
  1558.     BlockMove(HS.progname+1, HS.progname + 3, 253);
  1559.     HS.progname[0] += 2;
  1560.     HS.progname[1] = '-';
  1561.     HS.progname[2] = 'f';
  1562.     SetPtrSize(HS.progname, HS.progname[0]+1);
  1563.     PtoCstr((StringPtr)HS.progname); /* also done by LoadHawkDlogFromHS */
  1564.     /* Restore saved invocation */
  1565.     if (ReadHAWKResource(HS.progname))
  1566.         LoadHawkDlogFromHS(dPtr, FALSE); /* Boolean progToo */
  1567.     theMenu = GetMHandle(MainProgramID);
  1568.     if (userLocated)
  1569.         SetItem(theMenu, 3, reply.fName);
  1570.     /* Enable Run and SaveSettings buttons */
  1571.     HiliteDlgControl(dPtr, 1, 0);
  1572.     HiliteDlgControl(dPtr, SaveHawkSetup, 0);
  1573.     if (item == 1)
  1574.         item = 3;
  1575.     SetPopupMark(MainProgramID, item);
  1576.  
  1577.     /* Redraw done by caller */
  1578.     }
  1579.  
  1580. /* Delete/add library. Add new item just before dash. */
  1581. void GetHawkLibraryName(short menuItem)
  1582.     {
  1583.     MenuHandle    theMenu;
  1584.     Point         where;
  1585.     SFReply     reply;
  1586.     SFTypeList     types;
  1587.     long        len;
  1588.     short            numTypes, numItems, which, i;
  1589.     Boolean        hasLib;
  1590.     
  1591.     theMenu = GetMHandle(LibraryID);
  1592.     numItems = CountMItems(theMenu);
  1593.     if (menuItem < numItems) /* delete */
  1594.         {
  1595.         DelMenuItem(theMenu, menuItem);
  1596.         if (numItems == 3)
  1597.             DelMenuItem(theMenu, 1); /* take out the dash */
  1598.         which = menuItem-1;
  1599.         if (HS.libraryname[which])
  1600.             {
  1601.             DisposPtr(HS.libraryname[which]);
  1602.             HS.libraryname[which] = NULL;
  1603.             /* consolidate pointers */
  1604.             if (which == NUMLIBS-1) return;
  1605.             BlockMove((Ptr)(&(HS.libraryname[which])), 
  1606.                 (Ptr)(&(HS.libraryname[which+1])), 
  1607.                 sizeof(char *) * (NUMLIBS-1 - which));
  1608.             }
  1609.         return;
  1610.         }
  1611.     /* add new library at end of list */
  1612.     which = 0;
  1613.     
  1614.     /* display dialog, get program name and input file name */
  1615.     types[0] = 'TEXT';
  1616.     types[1] = 'RRRS';
  1617.     numTypes = 2;
  1618.     GetDlogOrigin (getDlgID, &where);
  1619.     SFGetFile (where, (StringPtr)"\p", NULL, numTypes, types, NULL, &reply);
  1620.     if (!reply.good)
  1621.         return;
  1622.     HS.libraryname[which] = NewPtr(256);
  1623.     if (MemError() != noErr)
  1624.         {
  1625.         MemoryAlert();
  1626.         return;
  1627.         }
  1628.     AppendPStr((Byte *)(FullPathNameFromVRefNum(reply.vRefNum,(Byte *)(HS.libraryname[which]))),
  1629.         (Byte *)(reply.fName));
  1630.     /* stick -f in front */
  1631.     BlockMove(HS.libraryname[which]+1, HS.libraryname[which] + 3, 253);
  1632.     HS.libraryname[which][0] += 2;
  1633.     HS.libraryname[which][1] = '-';
  1634.     HS.libraryname[which][2] = 'f';
  1635.     PtoCstr((StringPtr)HS.libraryname[which]);
  1636.     /* Set menu */
  1637.     if (numItems == 1)
  1638.         {
  1639.         InsMenuItem(theMenu, (StringPtr)"\pa", 0);
  1640.         SetItem(theMenu, 1, reply.fName);
  1641.         InsMenuItem(theMenu, (StringPtr)"\p-", 1);
  1642.         }
  1643.     else
  1644.         {
  1645.         InsMenuItem(theMenu, (StringPtr)"\pa", numItems-2);
  1646.         SetItem(theMenu, numItems-1, reply.fName);
  1647.         }
  1648.     }
  1649.  
  1650. void GetInputFileName()
  1651.     {
  1652.     MenuHandle    theMenu;
  1653.     Point         where;
  1654.     SFReply     reply;
  1655.     SFTypeList     types;
  1656.     long        len;
  1657.     short            numTypes;
  1658.     
  1659.     /* display dialog, get program name and input file name */
  1660.     types[0] = 'TEXT';
  1661.     types[1] = 'RRRS';
  1662.     numTypes = 2;
  1663.     GetDlogOrigin (getDlgID, &where);
  1664.     SFGetFile (where, (StringPtr)"\p", NULL, numTypes, types, NULL, &reply);
  1665.     if (!reply.good)
  1666.         return;
  1667.     
  1668.     if (HS.inputname)
  1669.         {
  1670.         DisposPtr(HS.inputname);
  1671.         HS.inputname = NULL;
  1672.         }
  1673.     HS.inputname = NewPtr(256);
  1674.     if (MemError() != noErr)
  1675.         {
  1676.         MemoryAlert();
  1677.         return;
  1678.         }
  1679.     AppendPStr((Byte *)(FullPathNameFromVRefNum(reply.vRefNum,(Byte *)(HS.inputname))),
  1680.         (Byte *)(reply.fName));
  1681.     PtoCstr((StringPtr)HS.inputname);
  1682.     /* Set menu */
  1683.     theMenu = GetMHandle(InputID);
  1684.     SetItem(theMenu, inPop.specificFile, reply.fName);
  1685.     }
  1686.  
  1687. /* Command line for awk proper, generated from user
  1688. dialog choices and variable entries.
  1689. HAWK -fProgname -fLibraries -vVariables -- inputfiles
  1690. */
  1691. Boolean GetCommandLineFromDlogResult()
  1692.     {
  1693.     long    len;
  1694.     short        i;
  1695.     
  1696.     if (!(HS.progname))
  1697.         {
  1698.         SysBeep(2); /* - can't do much without a program. */
  1699.         return(FALSE);
  1700.         }
  1701.     if (HS.inputType == inPop.specificFile && !(HS.inputname))
  1702.         {
  1703.         /* A suspicious case, arrived at either thru:
  1704.         - pick "Specific file..." option for input, and then cancel
  1705.             to, in effect, select the empty file; or
  1706.         - saved input option does not exist for this run, have defaulted
  1707.             to this case.
  1708.         Since a hAwk program can still do things in its BEGIN block even with
  1709.         no input file, allow the "no input at all" option to proceed. */
  1710.         ;
  1711.         }
  1712.     argc = 0;
  1713.     argv = (char **)NewPtr(sizeof(char *) * NUMARGVS);
  1714.     if (MemError() != noErr)
  1715.         {
  1716.         CleanUpAfterHAWK();
  1717.         return(FALSE);
  1718.         }
  1719.     /* hawk name always as first arg */
  1720.     len = strlen(gacc.thisCodeName);
  1721.     argv[argc] = NewPtr(len+1);
  1722.     if (!argv[argc])
  1723.         return(FALSE);
  1724.     BlockMove(gacc.thisCodeName, argv[argc], len+1);
  1725.     ++argc;
  1726.     
  1727.     argv[argc] = HS.progname;
  1728.     ++argc;
  1729.     for (i = 0; i < NUMLIBS; ++i)
  1730.         {
  1731.         if (!(HS.libraryname[i]))
  1732.             break;
  1733.         argv[argc] = HS.libraryname[i];
  1734.         ++argc;
  1735.         }
  1736.     /* variables */
  1737.     for (i = 0; i < NUMVARSETS; ++i)
  1738.         {
  1739.         if (!(HS.varsetting[i]))
  1740.             break;
  1741.         argv[argc] = HS.varsetting[i];
  1742.         ++argc;
  1743.         }
  1744.     /* the -- */
  1745.     len = 2;
  1746.     argv[argc] = NewPtr(len+1);
  1747.     if (MemError() != noErr)
  1748.         {
  1749.         CleanUpAfterHAWK();
  1750.         return(FALSE);
  1751.         }
  1752.     BlockMove("--", argv[argc], len+1);
  1753.     ++argc;
  1754.     /* lastly, get input file if any - note hAWK can still do things even
  1755.     if no input file specified in command line. */
  1756.     if (HS.inputType == inPop.frontSelected || HS.inputType == inPop.frontAll)
  1757.         {
  1758.         argv[argc] = CreateStdIn(HS.inputType == inPop.frontAll);
  1759.         if (!argv[argc])
  1760.             {
  1761.             CleanUpAfterHAWK();
  1762.             return(FALSE);
  1763.             }
  1764.         ++argc;
  1765.         }
  1766.     else if (HS.inputType == inPop.multiSelected)
  1767.         {
  1768.         if (!GetInputsFromMFS())
  1769.             {
  1770.             CleanUpAfterHAWK();
  1771.             return(FALSE);
  1772.             }
  1773.         }
  1774.     else if (HS.inputType == inPop.specificFile && HS.inputname)
  1775.         {
  1776.         argv[argc] = HS.inputname;
  1777.         ++argc;
  1778.         }
  1779.     return(TRUE);
  1780.     }
  1781.  
  1782. /* If user wants the input to be whatever is in the front text file,
  1783. get a copy of the text and write it the the file used for standard input. */
  1784. char *CreateStdIn(Boolean wholeFile)
  1785.     {
  1786.     Ptr            copyOfName;
  1787.     Handle        hText;
  1788.     long        len;
  1789.     OSErr         IOResult;
  1790.     short             refNum;
  1791.     
  1792.     /* anything? */
  1793.     if (HasGetFrontText())
  1794.         {
  1795.         hText = GetFrontText(wholeFile);
  1796.         }
  1797.     else
  1798.         hText = NewHandle(0);
  1799.     if (!hText)
  1800.         return(NULL);
  1801.         
  1802.     /* save to standard input file */
  1803.     /* Delete the file.  We don't care if there's an error */
  1804.     FSDelete((StringPtr)gacc.stdInFileNameP, 0);
  1805.     
  1806.     /* Now try to create it. '????' is the creator. Report the file error, if any */
  1807.     if (IOResult = Create((StringPtr)gacc.stdInFileNameP, 0, '????', 'TEXT'))
  1808.         {
  1809.         DisposHandle(hText);
  1810.         OKStopAlert("Standard input file could not be created.");
  1811.         return(NULL);
  1812.         }
  1813.     
  1814.     if (IOResult = FSOpen ((StringPtr)gacc.stdInFileNameP, 0, &refNum))
  1815.         {
  1816.         DisposHandle(hText);
  1817.         OKStopAlert("Standard input file could not be opened.");
  1818.         return(NULL);
  1819.         }
  1820.     len = GetHandleSize(hText);
  1821.     if (IOResult = FSWrite (refNum, &len, *hText))
  1822.         {
  1823.         FSClose (refNum);
  1824.         DisposHandle(hText);
  1825.         OKStopAlert("Standard input file could not be written to.");
  1826.         return(NULL);
  1827.         }
  1828.     FSClose (refNum);
  1829.     DisposHandle(hText);
  1830.     /* return ptr to copy of gacc.stdInFileName if success, or NULL */
  1831.     len = strlen(gacc.stdInFileName);
  1832.     copyOfName = NewPtr(len+1);
  1833.     if (!copyOfName)
  1834.         return(NULL);
  1835.     BlockMove(gacc.stdInFileName, copyOfName, len+1);
  1836.     return(copyOfName);
  1837.     }
  1838.  
  1839. /* Build list of files from multi-file search or equivalent selection.
  1840. This version, concoct full path name for each file.
  1841. Next version, use dirID and save much space. */
  1842. Boolean GetInputsFromMFS()
  1843.     {
  1844.     char            **newArgv;
  1845.     Byte            *tempPtr, *endPtr;
  1846.     short                whichPane, index, vRefNum, lastvrefnum = 0;
  1847.     char            fileName[32];
  1848.     
  1849.     if (!HasGetNextMultiFile()) return(FALSE);
  1850.     /* determine which file to search next */
  1851.     whichPane = -1;
  1852.     GetNextMultiFile(&whichPane, &index, &vRefNum, fileName, FALSE);
  1853.     if (index < 0)
  1854.         return(FALSE);
  1855.     while (index >= 0)
  1856.         {
  1857.         tempPtr = (Byte *)NewPtr(256);
  1858.         if (MemError() != noErr)
  1859.             return(FALSE);
  1860.         /* This is a prime target for optimizing, since it does a lot of
  1861.         disk-pounding to retrieve the full path name. Detecting a run of
  1862.         the same vrefnum certainly helps.*/
  1863.         if (vRefNum != lastvrefnum) /* do it the hard way */
  1864.         AppendPStr((Byte *)(FullPathNameFromVRefNum(vRefNum, tempPtr)),
  1865.                 (Byte *)(fileName));
  1866.         else
  1867.             {
  1868.             BlockMove(argv[argc-1], (Ptr)tempPtr, 256);
  1869.             CtoPstr((Ptr)tempPtr);
  1870.             /* strip previous file name */
  1871.             endPtr = tempPtr + tempPtr[0];
  1872.             while (*endPtr != ':')
  1873.                 --endPtr;
  1874.             tempPtr[0] = (unsigned char)(endPtr - tempPtr);
  1875.             /* append new file name */
  1876.             AppendPStr(tempPtr, (Byte *)(fileName));
  1877.             }
  1878.         SetPtrSize((Ptr)tempPtr, tempPtr[0]+1);
  1879.         PtoCstr((StringPtr)tempPtr);
  1880.         argv[argc++] = (Ptr)tempPtr;
  1881.         lastvrefnum = vRefNum;
  1882.         GetNextMultiFile(&whichPane, &index, &vRefNum, fileName, FALSE);
  1883.         if (index >= 0 && argc > NUMARGVS - 1)
  1884.             { /* This is the only place where argv[] can overflow */
  1885.             NUMARGVS += 100; /* Apologies, NUMARGVS is actually a variable */
  1886.             newArgv = (char **)NewPtr(sizeof(char *) * NUMARGVS);
  1887.             if (MemError() != noErr)
  1888.                 return(FALSE);
  1889.             BlockMove((Ptr)argv, (Ptr)newArgv, sizeof(char *) * (NUMARGVS - 100));
  1890.             DisposPtr((Ptr)argv);
  1891.             argv = newArgv;
  1892.             }
  1893.         }
  1894.     return(TRUE);
  1895.     }
  1896.  
  1897. /* Bail out if error during hAWK run. */
  1898. void JumpOnHAWKError(short inputErrorNumber)
  1899.     {
  1900.     
  1901.     gInputError = inputErrorNumber;
  1902.     longjmp(envBuf, 1); /* return to save point */
  1903.     }
  1904.  
  1905. void CleanUpAfterHAWK(void)
  1906.     {
  1907.     /* Call TFreeAll if using TMalloc etc, call FFreeAll if using Fmalloc etc
  1908.     -at present, using Fmalloc which is better on all scores. */
  1909.     
  1910.     FFreeAll();
  1911.     alloca(0);
  1912.     //DumpZoneList(); with MW dont't have this any more
  1913.     
  1914.     while (--argc >= 0)
  1915.         {
  1916.         if (argv[argc])
  1917.             DisposPtr(argv[argc]);
  1918.         }
  1919.     DisposPtr((Ptr)argv);
  1920.     DisposeProgress(); /* remove progress dialog from screen if present */
  1921.     }
  1922.  
  1923. void HandleHAWKError()
  1924.     {
  1925.     /* -future- use gInputError */
  1926.     SysBeep(2);
  1927.     }
  1928.  
  1929.  
  1930. static pascal void EmptyExitToShell(void);
  1931. enum
  1932.     {
  1933.     uppExitToShellProcInfo = kPascalStackBased
  1934.     };
  1935. // Patch ExitToShell out temporarily and call exit()
  1936. void DoExiting(void)
  1937.     {
  1938.     pascal void (*gOldExitToShell)(void);
  1939.     UniversalProcPtr EmptyExitToShellProcPtr;
  1940.     
  1941.     gOldExitToShell = (void *)GetToolTrapAddress(0xA9F4);
  1942.     EmptyExitToShellProcPtr = NewRoutineDescriptor((ProcPtr)&EmptyExitToShell,
  1943.                                     uppExitToShellProcInfo,
  1944.                                     GetCurrentISA());
  1945.     SetToolTrapAddress(EmptyExitToShellProcPtr, 0xA9F4);
  1946.     exit(0);
  1947.     SetToolTrapAddress((UniversalProcPtr)gOldExitToShell, 0xA9F4);
  1948.     }
  1949.  
  1950. static pascal void EmptyExitToShell(void)
  1951.     {
  1952.     ;
  1953.     }
  1954.